package spitfire.ksim.algorithm;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import spitfire.ksim.data.TSDRequestData;
import spitfire.ksim.data.TSDRequestData.RequestEntry;

/**
 * <p>
 * There is a list of {@link FuzzyEntry} for each semantic description(SD) in 
 * the rule base. Calculate the similarity score between each {@link FuzzyEntry}
 * in one list and one type of sensor in the node. Denote the similarity score
 * as the score for this SD and this type. For one SD, sum up the score for this
 * SD and all sensor types, and get a score for this SD. Finally compare the score
 * among all SDs and choose the SD with the highest score.
 * </p>
 * 
 * @author Adam
 */
public class AccumulativeSelection implements RequestAlgorithm {
	
	@Override
	public String requestForSD(List<FuzzyEntry> fuzzyEntryList, 
			TSDRequestData requestData) {
		System.out.println("Requesting with Accumulative");
		// Map for recording the score sum for each SD
		Map<String, Double> sdScoreSumMap = new HashMap<String, Double>();

		List<RequestEntry> requestEntryList = requestData.getData();
		// For each sensor request entry
		for (RequestEntry requestEntry : requestEntryList) {
			String sensorType = requestEntry.sensorType;
			List<Double> dataList = requestEntry.sensorSnapshot.getDataList();
			
			System.out.println("Calculate score for <" + sensorType + ">");
			
			Map<String, Double> sdScoreMap = new HashMap<String, Double>();
			for (FuzzyEntry fe : fuzzyEntryList) {
				double sc = SimilarityAlgorithm.calculateScore(dataList, fe.getRule());
				String sd = fe.getSd();
				if (!sdScoreMap.containsKey(sd) || sdScoreMap.get(sd) < sc) {
					// keep down the highest score for each SD 
					sdScoreMap.put(sd, sc);
				}
			}
			// calculate SUM of similarity for each SD 
			for (Entry<String, Double> sdScoreEntry : sdScoreMap.entrySet()) {
				String sd = sdScoreEntry.getKey();
				Double sc = sdScoreEntry.getValue();
				System.out.println("Similarity to <"+sd+">: " + sc);
				if (sdScoreSumMap.containsKey(sd)) {
					Double scoreSum = sdScoreSumMap.get(sd);
					sdScoreSumMap.put(sd, (scoreSum + sc));
				} else {
					sdScoreSumMap.put(sd, sc);
				}
			}
		}
		
		String maxSD = null;
		double maxSc = 0;
		for (Entry<String, Double> sdScoreSumEntry : sdScoreSumMap.entrySet()) {
			String sd = sdScoreSumEntry.getKey();
			double score = sdScoreSumEntry.getValue();
			if (score > maxSc) {
				maxSc = score;
				maxSD = sd;
			}
		}
		
		if (maxSD == null) {
			System.out.println("No SD selected");
		} else {
			System.out.println("<" + maxSD + "> selected with total score: " + maxSc);
		}
		return maxSD;
	}
}
